package com.syf.config.exception;

import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.syf.config.result.DefaultErrorResult;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;

/**
 * @desc 统一异常处理器
 *
 * @author hqf
 */
@RestController
@ControllerAdvice //二合一：@RestControllerAdvice
public class GlobalExceptionHandler extends BaseGlobalExceptionHandler {

	/**
	 * 一般entity的参数校验，异常就这如下三种:【处理400类异常】
	 * 		BindException   				   处理参数绑定时异常
	 * 		MethodArgumentNotValidException	   处理使用@Validated注解时，参数验证错误异常
	 * 		ConstraintViolationException       处理验证参数封装错误时异常
	 */
	@Override
	@ResponseStatus(HttpStatus.BAD_REQUEST)   //为了改变HTTP响应的状态码
	@ExceptionHandler(ConstraintViolationException.class)  //指定该方法 处理指定异常
	public DefaultErrorResult handleConstraintViolationException(ConstraintViolationException e, HttpServletRequest request) {
		return super.handleConstraintViolationException(e, request);
	}

	/**
	 * 方法参数校验失败的异常
	 *
	 */
	@Override
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	@ExceptionHandler(BindException.class)
	public DefaultErrorResult handleBindException(BindException e, HttpServletRequest request) {
		return super.handleBindException(e, request);
	}

	/**
	 * 前端 以json格式传参 @Validated @Valid校验出现异常
	 */
	@Override
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public DefaultErrorResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
		return super.handleMethodArgumentNotValidException(e, request);
	}


	/**
	 * 前端页面传过来的参数与你controller接收的 参数类型不匹配
	 */
	@Override
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	@ExceptionHandler(HttpMessageNotReadableException.class)
	public DefaultErrorResult handleConstraintViolationException(HttpMessageNotReadableException e, HttpServletRequest request) {
		return super.handleConstraintViolationException(e, request);
	}


	/**
	 * 处理自定义异常(BizException): 开发人员手动throw 抛出来的异常
	 */
	@Override
	@ExceptionHandler(BizException.class)
	public ResponseEntity<DefaultErrorResult> handleBusinessException(BizException e, HttpServletRequest request) {
		return super.handleBusinessException(e, request);
	}


	/**
	 * 内部API调用的异常处理
	 */
	@Override
	@ExceptionHandler(ApiException.class)
	public DefaultErrorResult handleApiException(ApiException e, HttpServletRequest request) {
		return super.handleApiException(e, request);
	}


	/**
	 * 处理未预测到的其他错误
	 */
	@Override
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	@ExceptionHandler(Throwable.class)
	public DefaultErrorResult handleThrowable(Throwable e, HttpServletRequest request) {
		//TODO 可通过邮件、微信公众号等方式发送信息至开发人员、记录存档等操作
		return super.handleThrowable(e, request);
	}

}
